class IUP_FLAT_TABS
-- Creates a native container for composing elements in hidden layers with only 
-- one layer visible (just like IupZbox), but its visibility can be 
-- interactively controlled. The interaction is done in a line of tabs with 
-- titles and arranged according to the tab type. Also known as Notebook in 
-- native systems. Identical to the IUP_TABS control but the decorations and 
-- buttons are manually drawn. It inherits from IUP_CANVAS. 

inherit
	IUP_CANVAS
		redefine
			execute_flat_button,
			execute_flat_motion,
			execute_flat_leavewindow,
			execute_tabchange,
			execute_tabchangepos,
			execute_tabclose,
			execute_rightclick,
			execute_extrabutton
		end
	IUP_WIDGET_CLIENTSIZE
	IUP_WIDGET_CLIENTOFFSET
	IUP_WIDGET_NAME
	IUP_WIDGET_FLAT_TEXT
	IUP_WIDGET_FLOATING
	IUP_WIDGET_CHILDSIZEALL

create {ANY}
	flat_tabs_empty,
	flat_tabs

feature {ANY}

	flat_tabs_empty
	   -- Create an empty flat tabs
		local
			p, a_flat_tabs: POINTER
		do
			a_flat_tabs := int_flat_tabs_empty (p)
			set_widget(a_flat_tabs)
		end
		
	flat_tabs (col: ARRAY[IUP_WIDGET])
	   -- Create a new flat tabs containing the list of widgets
		local
         iterator: ITERATOR[IUP_WIDGET]; i: INTEGER; arg: NATIVE_ARRAY[POINTER]; s: IUP_WIDGET; a_flat_tabs: POINTER
		do
			i := col.count
			arg := arg.calloc(i)
			iterator := col.new_iterator
			i := 0
			
			from
				iterator.start
         until
				iterator.is_off
         loop
            s := iterator.item
            arg.put(s.widget, i)
				iterator.next
            i := i + 1
         end

			a_flat_tabs := int_flat_tabs (arg.to_external)
			set_widget(a_flat_tabs)
		end

	-- Attributes

	set_rgb_fore_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Text color for the current Tab. Default: "50 150 255".
		do
			iup_open.set_attribute(Current, "FORECOLOR", rgb_to_string(red, green, blue))
		end

	get_rgb_fore_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "FORECOLOR")
		end

	set_rgb_highlight_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Text color for the highlighted Tab. The current Tab is never 
		-- highlighted, so it affects only the other tabs. If not defined 
		-- FORECOLOR will be used.
		do
			iup_open.set_attribute(Current, "HIGHCOLOR", rgb_to_string(red, green, blue))
		end

	get_rgb_highlight_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "HIGHCOLOR")
		end
	
	set_child_offset (horizontal, vertical: INTEGER)
		-- Allow to specify a position offset for the child. Available for native 
		-- containers only. It will not affect the natural size, and allows to 
		-- position controls outside the client area. Format "dxxdy", where dx 
		-- and dy are integer values corresponding to the horizontal and vertical 
		-- offsets, respectively, in pixels. Default: 0x0.
		require
			horizontal >= 0
			vertical >= 0
		local
			offset: STRING
		do
			offset := horizontal.to_string
			offset.append_string("x")
			offset.append_string(vertical.to_string)

			iup_open.set_attribute(Current, "CHILDOFFSET", offset)
		end

	get_child_offset: TUPLE[INTEGER, INTEGER]
		-- Return the offset of the child.
		local
			offset: STRING
		do
			offset := iup_open.get_attribute(Current, "CHILDOFFSET")
			Result := components_of_size(offset)
		end
	
	get_count: INTEGER
		-- (read-only) (non inheritable): returns the number of tabs.
		do
			Result := get_child_count
		end

	set_fixed_width (state: BOOLEAN)
		-- Forces all tabs to use the same width. Default: False.
		do
			iup_open.set_attribute(Current, "FIXEDWIDTH", boolean_to_yesno(state))
		end

	is_fixed_width: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "FIXEDWIDTH")

			Result := yesno_to_boolean(str)
		end

	set_show_close (state: BOOLEAN)
		-- Enables the close button on each tab. Default value: "False". By 
		-- default when closed the tab is hidden. To change that behavior use the 
		-- TABCLOSE_CB callback.
		do
			iup_open.set_attribute(Current, "SHOWCLOSE", boolean_to_yesno(state))
		end

	is_show_close: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "SHOWCLOSE")

			Result := yesno_to_boolean(str)
		end

	set_show_lines (state: BOOLEAN)
		-- When enabled the current tab will be separated of the other tabs by a 
		-- line. Default: True.
		do
			iup_open.set_attribute(Current, "SHOWLINES", boolean_to_yesno(state))
		end

	is_show_lines: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "SHOWLINES")

			Result := yesno_to_boolean(str)
		end

	set_tab_change_on_check (state: BOOLEAN)
		-- Call the TABCHANGE* callbacks when current tab is removed or hidden.
		-- Default: False.
		do
			iup_open.set_attribute(Current, "TABCHANGEONCHECK", boolean_to_yesno(state))
		end

	is_tab_change_on_check: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "TABCHANGEONCHECK")

			Result := yesno_to_boolean(str)
		end

	set_tabs_padding (horizontal, vertical: INTEGER)
		-- (non inheritable): internal margin of the tab title. Works just like 
		-- the MARGIN attribute of the IUP_HBOX and IUP_VBOX containers.
		-- Default value: "10x10".
		require
			horizontal >= 0
			vertical >= 0
		local
			padding: STRING
		do
			padding := horizontal.to_string
			padding.append_string("x")
			padding.append_string(vertical.to_string)

			iup_open.set_attribute(Current, "TABSPADDING", padding)
		end

	get_tabs_padding: TUPLE[INTEGER, INTEGER]
		-- Return the margin of the tab title.
		local
			padding: STRING
		do
			padding := iup_open.get_attribute(Current, "TABSPADDING")
			Result := components_of_size(padding)
		end

	set_tabs_rgb_fore_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Text color of the tabs that are not the current tab. Default: the 
		-- global attribute DLGFGCOLOR.
		do
			iup_open.set_attribute(Current, "TABSFORECOLOR", rgb_to_string(red, green, blue))
		end

	get_tabs_rgb_fore_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "TABSFORECOLOR")
		end

	set_tabs_rgb_background_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Background color of the tabs that are not the current tab. If not 
		-- defined it will use the background color of the parent.
		do
			iup_open.set_attribute(Current, "TABSBACKCOLOR", rgb_to_string(red, green, blue))
		end

	get_tabs_rgb_background_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "TABSBACKCOLOR")
		end

	set_tabs_rgb_highlight_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Background highlight color of the tabs that are not the current tab. 
		-- When not defined the background is not highlighted.
		do
			iup_open.set_attribute(Current, "TABSHIGHCOLOR", rgb_to_string(red, green, blue))
		end

	get_tabs_rgb_highlight_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "TABSHIGHCOLOR")
		end

	set_tabs_font (font: STRING)
		-- Text font of the tabs. When not defined FONT is used. It is a non 
		-- inheritable option for setting the font.
		do
			iup_open.set_attribute(Current, "TABSFONT", font)
		end

	get_tabs_font: STRING
		-- Return the string with the description of the used font.
		do
			Result := iup_open.get_attribute(Current, "TABSFONT")
		end

	set_tabs_font_style (fontstyle: STRING)
		-- Text font style. When change will actually set TABSFONT.
		do
			iup_open.set_attribute(Current, "TABSFONTSTYLE", fontstyle)
		end

	get_tabs_font_style: STRING
		-- Return the style of the current TABSFONTSTYLE attribute.
		do
			Result := iup_open.get_attribute(Current, "TABSFONTSTYLE")
		end

	set_tabs_font_size (fontsize: INTEGER)
		-- Text font size. When change will actually set TABSFONT.
		do
			iup_open.set_attribute(Current, "TABSFONTSIZE", fontsize.to_string)
		end

	get_tabs_font_size: INTEGER
		-- Return the style of the current TABSFONTSIZE attribute.
		local
			size: STRING
		do
			size := iup_open.get_attribute(Current, "TABSFONTSIZE")
			Result := size.to_integer
		end

	set_tabs_text_alignment (value: STRING)
		-- Horizontal text alignment for multiple lines. Can be: ALEFT, ARIGHT or 
		-- ACENTER. Default: ALEFT.
		require
			is_valid: is_valid_horizontal_alignment(value)
		do
			iup_open.set_attribute(Current, "TABSTEXTALIGNMENT", value)
		end

	get_tabs_text_alignment: STRING
		do
			Result := iup_open.get_attribute(Current, "TABSTEXTALIGNMENT")
		end

	set_tabs_text_wrap (state: BOOLEAN)
		-- (non inheritable): For single line texts if the text is larger than 
		-- its box the line will be automatically broken in multiple lines. 
		-- Notice that this is done internally by the system, the element natural 
		-- size will still use only a single line. For the remaining lines to be 
		-- visible the element should use EXPAND=VERTICAL or set a 
		-- SIZE/RASTERSIZE with enough height for the wrapped lines. 
		do
			iup_open.set_attribute(Current, "TABSTEXTWRAP", boolean_to_yesno(state))			
		end

	set_tabs_text_ellipsis (state: BOOLEAN)
		-- (non inheritable): If the text is larger that its box, an ellipsis 
		-- ("...") will be placed near the last visible part of the text and 
		-- replace the invisible part. It will be ignored when TEXTWRAP=True.
		do
			iup_open.set_attribute(Current, "TABSTEXTELLIPSIS", boolean_to_yesno(state))			
		end

	set_tabs_text_orientation (value: REAL_64)
		-- (non inheritable): text angle in degrees and counterclockwise. The 
		-- text size will adapt to include the rotated space.
		do
			iup_open.set_attribute(Current, "TABSTEXTORIENTATION", value.to_string)
		end

	set_tab_type_top
		-- The default value. It will not automatically change the TABORIENTATION.
		-- When changed with the dialog visible the application should call 
		-- "refresh" or "refresh_children" to updated the layout when ready.
		do
			iup_open.set_attribute(Current, "TABTYPE", "TOP")
		end

	set_tab_type_bottom
		-- It will not automatically change the TABORIENTATION. When changed with 
		-- the dialog visible the application should call "refresh" or 
		-- "refresh_children" to updated the layout when ready.
		do
			iup_open.set_attribute(Current, "TABTYPE", "BOTTOM")
		end

	set_tab_type_left
		-- It will not automatically change the TABORIENTATION. When changed with 
		-- the dialog visible the application should call "refresh" or 
		-- "refresh_children" to updated the layout when ready.
		do
			iup_open.set_attribute(Current, "TABTYPE", "LEFT")
		end

	set_tab_type_right
		-- It will not automatically change the TABORIENTATION. When changed with 
		-- the dialog visible the application should call "refresh" or 
		-- "refresh_children" to updated the layout when ready.
		do
			iup_open.set_attribute(Current, "TABTYPE", "RIGHT")
		end

	set_tab_orientation_horizontal
		-- Horizontal orientation of tab text. Thi is the default value.
		do
			iup_open.set_attribute(Current, "TABORIENTATION", "HORIZONTAL")
		end

	set_tab_orientation_vertical
		-- When set to vertical it will simply set_tabs_text_orientation=90.
		do
			iup_open.set_attribute(Current, "TABORIENTATION", "VERTICAL")
		end

	set_tabs_rgb_line_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Color of the separator line. Default: "180 180 180".
		do
			iup_open.set_attribute(Current, "TABSLINECOLOR", rgb_to_string(red, green, blue))
		end

	get_tabs_rgb_line_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "TABSLINECOLOR")
		end

	set_tabs_image_position (value: STRING)
		-- Position of the image relative to the text when both are displayed. 
		-- Can be: LEFT, RIGHT, TOP, BOTTOM. Default: LEFT.
		require
			is_valid: is_valid_position(value)
		do
			iup_open.set_attribute(Current, "TABSIMAGEPOSITION", value)
		end

	get_tabs_image_position: STRING
		do
			Result := iup_open.get_attribute(Current, "TABSIMAGEPOSITION")
		end

	set_tabs_image_spacing (value: INTEGER)
		-- Spacing between the image and the text. Default: "2".
		require
			positive: value >= 0
		do
			iup_open.set_attribute(Current, "TABSIMAGESPACING", value.to_string)
		end

	get_tabs_image_spacing: STRING
		do
			Result := iup_open.get_attribute(Current, "TABSIMAGESPACING")
		end

	set_tabs_alignment (horizontal, vertical: STRING)
		-- Horizontal and vertical alignment of the set image+text. Possible 
		-- values: "ALEFT", "ACENTER" and "ARIGHT", combined to "ATOP", "ACENTER" 
		-- and "ABOTTOM". Default: "ACENTER:ACENTER".
		require
			is_valid_tabs_alignment(horizontal, vertical)
		local
			str: STRING
		do
			create str.copy(horizontal)
	      str.append_string(":")
 	      str.append_string(vertical)
	
			iup_open.set_attribute(Current, "TABSALIGNMENT", str)
		end

	get_tabs_alignment: TUPLE[INTEGER, INTEGER]
		-- Return the horizontal and vertical alignment.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "TABSALIGNMENT")

			Result := components_of(str, ':')
		end

	-- Tab Attributes (non inheritable)

	set_tab_n_image (imagename: STRING; n: INTEGER)
		-- Image name to be used in the respective tab. Use 
		-- set_attribute_handle to associate an image to a name. n starts at 0. 
		-- See also IUP_IMAGE.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABIMAGE", n, imagename)
		end

	get_tab_n_image (n: INTEGER): STRING
   	-- Return the image name at tab n.
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABIMAGE", n)
		end

	set_tab_n_image_highlight (imagename: STRING; n: INTEGER)
		-- Same as set_tab_n_image when in highlight state. If not defined 
		-- tab n image is used.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABIMAGEHIGHTLIGHT", n, imagename)
		end

	get_tab_n_image_highlight (n: INTEGER): STRING
   	-- Return the image highlight name at tab n.
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABIMAGEHIGHTLIGHT", n)
		end

	set_tab_n_image_inactive (imagename: STRING; n: INTEGER)
		-- Same as set_tab_n_image when in inactive state. If not defined 
		-- tab n image is used and its colors will be replaced by a modified 
		-- version creating the disabled effect.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABIMAGEINACTIVE", n, imagename)
		end

	get_tab_n_image_inactive (n: INTEGER): STRING
   	-- Return the image inactive name at tab n.
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABIMAGEINACTIVE", n)
		end

	set_tab_n_visible (state: BOOLEAN; n: INTEGER)
		-- Allows to hide a tab. n starts at 0. When a tab is hidden the tabs 
		-- indices are not changed.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "TABVISIBLE", n, boolean_to_yesno(state))
		end

	is_tab_n_visible (n: INTEGER): BOOLEAN
   	-- Return the visible status of tab n.
		require
		   n >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "TABVISIBLE", n)
			Result := yesno_to_boolean(str)
		end

	set_tab_n_title (title: STRING; n: INTEGER)
		-- Contains the text to be shown in the respective tab title. n starts
		-- at 0.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "TABTITLE", n, title)
		end

	get_tab_n_title (n: INTEGER): STRING
   	-- Return the title of tab n.
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABTITLE", n)
		end

	set_tab_n_active (state: BOOLEAN; n: INTEGER)
		-- Active state of the tab. Default: True.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABACTIVE", n, boolean_to_yesno(state))
		end

	is_tab_n_active (n: INTEGER): BOOLEAN
   	-- Return the tab n active state.
		require
		   n >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "TABACTIVE", n)

			Result := yesno_to_boolean(str)
		end

	set_tab_n_rgb_fore_color (red, green, blue, n: INTEGER)
		-- Text color of the tab title. When not defined TABSFORECOLOR is used.
		require
		   n >= 0
		do
			iup_open.set_attribute_id(Current, "TABFORECOLOR", n, rgb_to_string(red, green, blue))
		end

	get_tab_n_rgb_fore_color (n: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
		   n >= 0
		do
			Result := iup_open.get_rgb_id(Current, "TABFORECOLOR", n)
		end

	set_tab_n_rgb_background_color (red, green, blue, n: INTEGER)
		-- Background color of the tab. When not defined TABSBACKCOLOR is used.
		require
		   n >= 0
		do
			iup_open.set_attribute_id(Current, "TABBACKCOLOR", n, rgb_to_string(red, green, blue))
		end

	get_tab_n_rgb_background_color (n: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
		   n >= 0
		do
			Result := iup_open.get_rgb_id(Current, "TABBACKCOLOR", n)
		end

	set_tab_n_rgb_highlight_color (red, green, blue, n: INTEGER)
		-- Highlight color of the tab title. When not defined TABSHIGHCOLOR is 
		-- used.	
		require
		   n >= 0
		do
			iup_open.set_attribute_id(Current, "TABHIGHCOLOR", n, rgb_to_string(red, green, blue))
		end

	get_tab_n_rgb_highlight_color (n: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
		   n >= 0
		do
			Result := iup_open.get_rgb_id(Current, "TABHIGHCOLOR", n)
		end

	set_tab_n_font (font: STRING; n: INTEGER)
		-- Text font of the tab. When not defined TABSFONT is used.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABFONT", n, font)
		end

	get_tab_n_font (n: INTEGER): STRING
		require
			n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABFONT", n)
		end

	set_tab_n_font_style (fontstyle: STRING; n: INTEGER)
		-- Text font style. When change will actually set TABFONTn.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABFONTSTYLE", n, fontstyle)
		end

	get_tab_n_font_style (n: INTEGER): STRING
		require
			n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABSFONTSTYLE", n)
		end

	set_tab_n_font_size (fontsize, n: INTEGER)
		-- Text font size. When change will actually set TABFONTn. 
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABFONTSIZE", n, fontsize.to_string)
		end

	get_tab_n_font_size (n: INTEGER): INTEGER
		require
			n >= 0
		local
			size: STRING
		do
			size := iup_open.get_attribute_id(Current, "TABFONTSIZE", n)
			Result := size.to_integer
		end

	set_tab_n_tip (tip: STRING; n: INTEGER)
		-- TIP of the tab.
		require
			n >= 0
		do
			iup_open.set_attribute_id(Current, "TABTIP", n, tip)
		end

	get_tab_n_tip (n: INTEGER): STRING
		require
			n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABTIP", n)
		end

	-- Tab Close Button Attributes

	set_tab_close_image (imagename: STRING)
		-- Image name to be used in the close button. Use 
		-- set_attribute_handle to associate an image to a name. n starts at 0. 
		-- See also IUP_IMAGE. Default: "IMGFLATCLOSE".
		do
			iup_open.set_attribute(Current, "CLOSEIMAGE", imagename)
		end

	get_tab_close_image: STRING
		do
			Result := iup_open.get_attribute(Current, "TABIMAGE")
		end

	set_tab_close_image_press (imagename: STRING)
		-- Image name to be used in the close button in pressed state.
		-- Default: "IMGFLATCLOSEPRESS".
		do
			iup_open.set_attribute(Current, "CLOSEIMAGEPRESS", imagename)
		end

	get_tab_close_image_press: STRING
		do
			Result := iup_open.get_attribute(Current, "CLOSEIMAGEPRESS")
		end

	set_tab_close_image_highlight (imagename: STRING)
		-- Image name to be used in the close button in highlight state.
		do
			iup_open.set_attribute(Current, "CLOSEIMAGEHIGHLIGHT", imagename)
		end

	get_tab_close_image_highlight: STRING
		do
			Result := iup_open.get_attribute(Current, "CLOSEIMAGEHIGHLIGHT")
		end

	set_tab_close_image_inactive (imagename: STRING)
		-- Image name to be used in the close button in inactive state. If it is 
		-- not defined then the CLOSEIMAGE is used and its colors will be 
		-- replaced by a modified version creating the disabled effect.
		do
			iup_open.set_attribute(Current, "CLOSEIMAGEINACTIVE", imagename)
		end

	get_tab_close_image_inactive: STRING
		do
			Result := iup_open.get_attribute(Current, "CLOSEIMAGEINACTIVE")
		end

	set_tab_rgb_close_press_color (red, green, blue: INTEGER)
		-- Background color of the close button in pressed state.
		-- Default: "80 180 245".
		do
			iup_open.set_attribute(Current, "CLOSEPRESSCOLOR", rgb_to_string(red, green, blue))
		end

	get_tabs_rgb_close_press_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "CLOSEPRESSCOLOR")
		end

	set_tab_rgb_close_highlight_color (red, green, blue: INTEGER)
		-- Background color of the close button in highlight state.
		-- Default: "200 220 245".
		do
			iup_open.set_attribute(Current, "CLOSEHIGHCOLOR", rgb_to_string(red, green, blue))
		end

	get_tabs_rgb_close_highlight_color: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			Result := iup_open.get_rgb(Current, "CLOSEHIGHCOLOR")
		end

	-- Extra Buttons Attributes (non inheritable)

	set_extra_buttons (buttons: INTEGER)
		-- Sets the number of extra image buttons at right in the free space 
		-- area. There can be any number of buttons. See the EXTRABUTTON_CB 
		-- callback. Default: 0.
		--
		-- Button id starts at 1, and are positioned from right to left. Just 
		-- like the tabs they do not affect natural width. But they also don't 
		-- affect the tabs title height, if button title or image are larger than 
		-- the tabs title height they will be cropped.
		require
			buttons >= 0
		do
			iup_open.set_attribute(Current, "EXTRABUTTONS", buttons.to_string)
		end

	get_extra_buttons: INTEGER
		do
			Result := iup_open.get_attribute(Current, "EXTRABUTTONS").to_integer
		end

	set_title_at_extra_button (title: STRING; button: INTEGER)
		-- Text of the respective button.
		require
			button >= 0
		do
			iup_open.set_attribute_id(Current, "EXTRATITLE", button, title)
		end

	get_title_at_extra_button (button: INTEGER): STRING
		require
			button >= 0
		do
			Result := iup_open.get_attribute_id(Current, "EXTRATITLE", button)
		end

	set_extra_button_active (button: INTEGER; state: BOOLEAN)
		require
			button >= 0
		do
			iup_open.set_attribute_id(Current, "EXTRAACTIVE", button, boolean_to_yesno(state))
		end

	is_extra_button_active (button: INTEGER): BOOLEAN
		require
			button >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "EXTRAACTIVE", button)

			Result := yesno_to_boolean(str)
		end

	set_extra_button_rgb_fore_color (red, green, blue, button: INTEGER)
		-- Text color of the button title. When not defined TABSFORECOLOR is used.
		require
			button >= 0
		do
			iup_open.set_attribute_id(Current, "EXTRAFORECOLOR", button, rgb_to_string(red, green, blue))
		end

	get_extra_button_rgb_fore_color (button: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
		   button >= 0
		do
			Result := iup_open.get_rgb_id(Current, "EXTRAFORECOLOR", button)
		end

	set_extra_button_rgb_press_color (red, green, blue, button: INTEGER)
		-- Background color of the button in pressed state.
		-- Default: "150 200 235".
		require
			button >= 0
		do
			iup_open.set_attribute_id(Current, "EXTRAPRESSCOLOR", button, rgb_to_string(red, green, blue))
		end

	get_extra_button_rgb_press_color (button: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
		   button >= 0
		do
			Result := iup_open.get_rgb_id(Current, "EXTRAPRESSCOLOR", button)
		end

	set_extra_button_rgb_highlight_color (red, green, blue, button: INTEGER)
		-- Background color of the button in highlight state.
		-- Default: "200 225 245".
		require
			button >= 0
		do
			iup_open.set_attribute_id(Current, "EXTRAHIGHCOLOR", button, rgb_to_string(red, green, blue))
		end

	get_extra_button_rgb_highlight_color (button: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
		   button >= 0
		do
			Result := iup_open.get_rgb_id(Current, "EXTRAHIGHCOLOR", button)
		end

	set_extra_button_font (font: STRING; button: INTEGER)
		-- Text font of the tab. When not defined TABSFONT is used.
		require
			button >= 0
		do
			iup_open.set_attribute_id(Current, "EXTRAFONT", button, font)
		end

	get_extra_button_font (button: INTEGER): STRING
		require
			button >= 0
		do
			Result := iup_open.get_attribute_id(Current, "EXTRAFONT", button)
		end

	set_extra_button_n_image (imagename: STRING; n: INTEGER)
		-- Image name to be used in the respective button.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "TABIMAGE", n, imagename)
		end

	get_extra_button_n_image (n: INTEGER): STRING
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABIMAGE", n)
		end

	set_extra_button_n_image_press (imagename: STRING; n: INTEGER)
		-- Image name to be used in the respective button when pressed. If not 
		-- defined the IMAGE will be used.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "TABIMAGEPRESS", n, imagename)
		end

	get_extra_button_n_image_press (n: INTEGER): STRING
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TABIMAGEPRESS", n)
		end

	set_extra_button_n_image_highlight (imagename: STRING; n: INTEGER)
		-- Image name to be used in the respective button when highlighted. If 
		-- not defined IMAGE will be used.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "EXTRAIMAGEHIGHLIGHT", n, imagename)
		end

	get_extra_button_n_image_highlight (n: INTEGER): STRING
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "EXTRAIMAGEHIGHLIGHT", n)
		end

	set_extra_button_n_image_inactive (imagename: STRING; n: INTEGER)
		-- Image name to be used in the respective button when highlighted. If 
		-- not defined IMAGE will be used and its colors will be replaced by a 
		-- modified version creating the disabled effect.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "EXTRAIMAGEINACTIVE", n, imagename)
		end

	get_extra_button_n_image_inactive (n: INTEGER): STRING
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "EXTRAIMAGEINACTIVE", n)
		end

	set_extra_button_n_tip (tip: STRING; n: INTEGER)
		-- Tip of the button.
		require
			n >= 0
		do
			iup_open.set_attribute_id (Current, "EXTRATIP", n, tip)
		end

	get_extra_button_n_tip (n: INTEGER): STRING
		require
		   n >= 0
		do
			Result := iup_open.get_attribute_id(Current, "EXTRATIP", n)
		end

	-- Expand Button Attributes (non inheritable)

	set_extra_expand_button (state: BOOLEAN)
		-- Uses the next free extra button to configure an expand button. The 
		-- button allows to dynamically expand and collapse the tabs contents. 
		-- When collapsed a click on a tab causes that tab to be temporarily 
		-- expanded until it looses the focus.
		do
			iup_open.set_attribute(Current, "EXPANDBUTTON", boolean_to_yesno(state))
		end

	has_extra_expand_button: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EXPANDBUTTON")

			Result := yesno_to_boolean(str)
		end

	get_expand_button_position: INTEGER
		-- (read-only): position of the expand button in the extra buttons.
		do
			Result := iup_open.get_attribute(Current, "EXPANDBUTTONPOS").to_integer
		end

	set_expand_button_state (state: BOOLEAN)
		-- Set the expand button state. True: Expanded. False: Collapsed.
		-- Default: True.
		do
			iup_open.set_attribute(Current, "EXPANDBUTTONSTATE", boolean_to_yesno(state))
		end

	get_expand_button_state: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EXPANDBUTTONSTATE")

			Result := yesno_to_boolean(str)
		end

	-- Current Tab (non inheritable)

	set_value (name: STRING)
		-- Changes the current tab by its name. The value passed must be the name 
		-- of one of the elements contained in the tabs. Use set_attribute_handle 
		-- to associate a child to a name.
		do
			iup_open.set_attribute(Current, "VALUE", name)
		end
	
	get_value: STRING
		-- Return the name of the visible child.
		do
			Result := iup_open.get_attribute(Current, "VALUE")
		end

	set_value_widget (wgt: IUP_WIDGET)
		-- Changes the current tab by its widget. The value passed must be the 
		-- widget of a child contained in the tabs. When the tabs is created, the 
		-- first element inserted is set as the visible child.
		do
			iup_open.set_attribute_widget(Current, "VALUE_HANDLE", wgt)
		end

	get_value_widget: IUP_WIDGET
		-- Return the IUP_WIDGET that is visible.
		do
			Result := iup_open.get_attribute_widget(Current, "VALUE_HANDLE")
		end

	set_value_position (value: INTEGER)
		-- Changes the current tab by its position, starting at 0. When the tabs 
		-- is created, the first element inserted is set as the visible child. In 
		-- GTK, inside the callback the returned value is still the previous one.
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "VALUEPOS", value.to_string)
		end

	get_value_position: INTEGER
		-- Return the position of the visible tab.
		do
			Result := iup_open.get_attribute(Current, "VALUEPOS").to_integer
		end

	-- Coordination to pos
	convert_xy_to_pos (x, y: INTEGER): INTEGER
		-- To convert (x,y) coordinates in tab position (same as VALUEPOS).
		do
			Result := iup_open.iup_convert_xy_to_pos (Current, x, y)	
		end

	-- Callbacks

	set_cb_flat_button (act: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when any mouse button is pressed and when it is 
		-- released. Both calls occur before the ACTION callback when button 1 is 
		-- being used.
		-- IUP_CANVAS: identifies the element that activated the event.
		-- button: identifies the activated mouse button:
		--
		-- 1 - left mouse button (button 1);
		-- 2 - middle mouse button (button 2);
		-- 3 - right mouse button (button 3).
		--
		-- pressed: indicates the state of the button:
		--
		-- 0 - mouse button was released;
		-- 1 - mouse button was pressed.
		-- 
		-- x, y: position in the canvas where the event has occurred, in pixels.
		--
		-- status: status of the mouse buttons and some keyboard keys at the 
		-- moment the event is generated. The following macros must be used for 
		-- verification:
		--
		-- Returns: IUP_CLOSE will be processed. On some controls if IUP_IGNORE 
		-- is returned the action is ignored (this is system dependent).
		local
			operation: INTEGER
		do
			cb_flat_button := act

			if cb_flat_button /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "FLAT_BUTTON_CB", "NONEEDED", operation)
		end

	set_cb_flat_motion (act: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when the mouse moves.
		-- ih: identifier of the element that activated the event.
		-- x, y: position in the canvas where the event has occurred, in pixels.
		-- status: status of mouse buttons and certain keyboard keys at the 
		-- moment the event was generated. The same macros used for BUTTON_CB can 
		-- be used for this status.
		local
			operation: INTEGER
		do
			cb_flat_motion := act

			if cb_flat_motion /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "FALT_MOTION_CB", "NONEEDED", operation)
		end

	set_cb_flat_leave_window (act: FUNCTION[TUPLE[IUP_FLAT_TABS], STRING])
		-- Action generated when the mouse leaves the native element.
		local
			operation: INTEGER
		do
			cb_flat_leavewindow := act

			if cb_leavewindow /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "FLAT_LEAVEWINDOW_CB", "NONEEDED", operation)
		end

	-- Extra
	set_cb_tab_change (act: FUNCTION[TUPLE[IUP_FLAT_TABS, IUP_WIDGET, IUP_WIDGET], STRING])
		-- Callback called when the user shifts the active tab.
		local
			operation: INTEGER
		do
			cb_tabchange := act

			if cb_tabchange /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TABCHANGE_CB", "NONEEDED", operation)
		end

	set_cb_tab_change_position (act: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER], STRING])
		-- Callback called when the user shifts the active tab. Called only when 
		-- TABCHANGE_CB is not defined.
		local
			operation: INTEGER
		do
			cb_tabchangepos := act

			if cb_tabchangepos /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TABCHANGEPOS_CB", "NONEEDED", operation)
		end

	set_cb_tab_close (act: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER], STRING])
		-- [Windows and GTK Only]: Callback called when the user clicks on the 
		-- close button. Called only when SHOWCLOSE=Yes.
		local
			operation: INTEGER
		do
			cb_tabclose := act

			if cb_tabclose /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TABCLOSE_CB", "NONEEDED", operation)
		end

	set_cb_right_click (act: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER], STRING])
		-- Callback called when the user clicks on some tab using the right mouse 
		-- button.
		local
			operation: INTEGER
		do
			cb_rightclick := act

			if cb_rightclick /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "RIGHTCLICK_CB", "NONEEDED", operation)
		end

	set_cb_extra_button (act: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER], STRING])
		-- Action generated when any mouse button is pressed or 
		-- released.
		--	ih: identifies the element that activated the event.
		-- button: identifies the extra button. can be 1, 2 or 3. (this is not 
		-- the same as BUTTON_CB)
		-- pressed: indicates the state of the button:
		-- 0 - mouse button was released;
		-- 1 - mouse button was pressed.
		local
			operation: INTEGER
		do
			cb_extrabutton := act

			if cb_extrabutton /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "EXTRABUTTON_CB", "NONEEDED", operation)
		end
				
feature {IUP}
	
	-- Callbacks

	execute_flat_button (btn, pressed, x, y: INTEGER; status: STRING): STRING
		do
			Result := cb_flat_button.item([Current, btn, pressed, x, y, status])
		end

	execute_flat_motion (x, y: INTEGER; status: STRING): STRING
		do
			Result := cb_flat_motion.item([Current, x, y, status])
		end

	execute_flat_leavewindow: STRING
		do
			Result := cb_flat_leavewindow.item([Current])
		end
	
	execute_tabchange (new_tab, old_tab: IUP_WIDGET): STRING
		do
			Result := cb_tabchange.item([Current, new_tab, old_tab])
		end

	execute_tabchangepos (new_pos, old_pos: INTEGER): STRING
		do
			Result := cb_tabchangepos.item([Current, new_pos, old_pos])
		end

	execute_tabclose (pos: INTEGER): STRING
		do
			Result := cb_tabclose.item([Current, pos])
		end

	execute_rightclick (pos: INTEGER): STRING
		do
			Result := cb_rightclick.item([Current, pos])
		end

	execute_extrabutton (button, pressed: INTEGER): STRING
		do
			Result := cb_extrabutton.item([Current, button, pressed])
		end

feature {}

	-- For Tabs callbacks

	cb_flat_button: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING]
	cb_flat_motion: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER, STRING], STRING]
	cb_flat_leavewindow: FUNCTION[TUPLE[IUP_FLAT_TABS], STRING]
	cb_tabchange: FUNCTION[TUPLE[IUP_FLAT_TABS, IUP_WIDGET, IUP_WIDGET], STRING]
	cb_tabchangepos: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER], STRING]
	cb_tabclose: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER], STRING]
	cb_rightclick: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER], STRING]
	cb_extrabutton: FUNCTION[TUPLE[IUP_FLAT_TABS, INTEGER, INTEGER], STRING]

	-- Internals
	
	int_flat_tabs_empty (arguments: POINTER): POINTER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "IupFlatTabs"
         }"
      end
	
   int_flat_tabs (arguments: POINTER): POINTER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "IupFlatTabsv"
         }"
      end

	-- Validations

	is_valid_position (type: STRING):  BOOLEAN
		do
			if type.is_equal("TOP") or
				type.is_equal("BOTTOM") or
				type.is_equal("LEFT") or
				type.is_equal("RIGHT") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_tabs_alignment (horizontal, vertical: STRING): BOOLEAN
		local
			h, v: BOOLEAN
		do
			if horizontal.is_equal("ALEFT") or
				horizontal.is_equal("ACENTER") or
				horizontal.is_equal("ARIGHT") then
				h := True
			else
				h := False
			end

			if vertical.is_equal("ATOP") or
				vertical.is_equal("ACENTER") or
				vertical.is_equal("ABOTTOM") then
				v := True
			else
				v := False
			end

			if h and v then
				Result := True
			else
				Result := False
			end
		end
end

-- The MIT License (MIT)

-- Copyright (c) 2017, 2019 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
